# 主程序调用界面文件

from base64 import b64encode, b64decode
import sys

from PyQt5.QtCore import QCoreApplication
from PyQt5.QtWidgets import QApplication, QMainWindow, QFileDialog, QWidget
from b64 import Ui_MainWindow
import xml.etree.ElementTree as ET

from b64_about import Ui_Dialog
from data.morse_data import morse_dict


class MyWindow(QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None):
        super(MyWindow, self).__init__(parent)
        self.setupUi(self)
        # 打开文件
        self.open_file.triggered.connect(self.show_text)
        # 退出
        self.exit.triggered.connect(QCoreApplication.quit)
        # base64模式
        self.actionbase64.triggered.connect(self.click_base64)
        # morse模式
        self.actionmorse.triggered.connect(self.click_morse)
        # 解码按钮
        self.decode_pushButton.clicked.connect(self.decode_button_fun)
        # 编码按钮
        self.encode_pushButton.clicked.connect(self.encode_button_fun)

        # 打开关于页面
        self.about.triggered.connect(show_about)

    def click_base64(self):
        is_base64_mode = self.actionbase64.isChecked()
        if not is_base64_mode:
            self.actionmorse.setChecked(True)
        else:
            self.actionmorse.setChecked(False)

    def click_morse(self):
        is_morse_mode = self.actionmorse.isChecked()
        if not is_morse_mode:
            self.actionbase64.setChecked(True)
        else:
            self.actionbase64.setChecked(False)

    def show_text(self):
        """
        将内容显示在窗口内
        :return:
        """
        fname = QFileDialog.getOpenFileName(self, '打开文件', './')
        if fname[0]:
            f = open(fname[0], 'r', encoding='utf-8')
            with f:
                data = f.read()
                self.decode_textEdit.setText(data)

    def decode_button_fun(self):
        """
        解码按钮功能，点击按钮，将加密的xml解码，并显示在右侧
        :return:
        """
        # 获取左侧文本框中的内容
        text = self.encode_textEdit.toPlainText()

        if self.actionbase64.isChecked():
            # 解码xml文件
            root = b64decode_text(text)
            if root is not None:
                # 解析格式正确
                decode_text = ET.tostring(root, 'utf-8').decode()
            else:
                # 解析格式错误
                decode_text = "xml格式错误，请检查xml格式！"
        elif self.actionmorse.isChecked():
            decode_text = get_word(text)

        # 将解码后的xml文件显示在右侧文本框中
        self.decode_textEdit.setText(decode_text)

    def encode_button_fun(self):
        """
        编码按钮功能，点击按钮，将xml加密，并显示在左侧
        :return:
        """
        # 获取decode_textBrowser文本框中的文本
        text = self.decode_textEdit.toPlainText()

        # tostring()只能从root节点解析
        # https://stackoverflow.com/questions/51660316/attributeerror-elementtree-object-has-no-attribute-tag-in-python
        # tostring()获得的是bite类型，通过decode()转化为str类型
        if self.actionbase64.isChecked():
            root = b64encode_text(text)
            if root is not None:
                encode_text = ET.tostring(root, 'utf-8').decode()
            else:
                encode_text = "xml格式错误，请检查xml格式！"
        elif self.actionmorse.isChecked():
            encode_text = get_morse_code(text)

        # 将编码后的内容显示在encode_textBrowser文本框中
        self.encode_textEdit.setText(encode_text)


class AboutWindow(QWidget, Ui_Dialog):
    def __init__(self):
        super(AboutWindow, self).__init__()
        self.setupUi(self)


def b64encode_text(text):
    """
    调用walk_data()方法，编码文档
    :param text:
    :return:
    """
    try:
        # 从字符串读取数据
        root = ET.fromstring(text)
        walk_data(root, "encode")
        return root
    except SyntaxError as e:
        return


def b64decode_text(text):
    """
    调用walk_data()方法，解码文档
    :param text:
    :return:
    """
    try:
        root = ET.fromstring(text)
        walk_data(root, "decode")
        return root
    except SyntaxError as e:
        return


def walk_data(root_node, function):
    """
    遍历所有的节点，将不为空的标签内容base64编解码
    :param root_node: xml
    :param function: encode:编码;decode:解码
    :return:
    """
    # 去除空格和换行
    text_val = root_node.text
    if text_val is not None:
        text_val = text_val.replace(" ", "").replace("\r", "").replace("\n", "")

        # 实现base64编码
        if text_val != "":
            if function == "encode":
                root_node.text = str(b64encode(text_val.encode()), "utf-8")
            if function == "decode":
                root_node.text = str(b64decode(text_val), "utf-8")

    # 遍历每个子节点
    if sys.version_info <= (2, 7):
        # python2.7，使用getchildren()函数
        children_node = root_node.getchildren()
    else:
        # python3+，使用list()函数
        children_node = list(root_node)

    if len(children_node) == 0:
        return
    for child in children_node:
        walk_data(child, function)


def get_morse_code(string):
    """
    将字符转化为莫斯密码
    :param string: 字符
    :return: 莫斯密码
    """
    code = ""
    string = string.strip()
    if len(string) != 0:
        string = string.upper()
        for item in string:
            try:
                item_code = morse_dict[item] + " "
            except KeyError:
                return "字符不支持"
            code += item_code
        return code.strip()
    else:
        return


def get_word(string):
    """
    将莫斯密码转换成字符
    :param string: 莫斯密码
    :return: 字符
    """
    word = ""
    string = string.strip()
    if len(string) != 0:
        code = string.split(" ")
        print(code)
        for item in code:
            decode_success = False
            for key, value in morse_dict.items():
                if item == value:
                    decode_success = True
                    word += key
            if not decode_success:
                return "莫斯密码有误"
    else:
        return
    return word


def show_about():
    aboutWin.show()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    # 主窗口
    myWin = MyWindow()
    # 关于窗口
    aboutWin = AboutWindow()

    myWin.show()
    sys.exit(app.exec_())
